﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SharpAnalyzer.Entities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SharpAnalyzer.Utilities
{
    internal sealed class MemberBodySelector
    {
        public static BlockSyntax FindBody(Member node)
        {
            BlockSyntax blockSyntax = null;
            switch (node.Kind)
            {
                case MemberKind.Method:
                case MemberKind.Constructor:
                case MemberKind.Destructor:
                    blockSyntax = ((BaseMethodDeclarationSyntax)node.SyntaxNode).Body;
                    break;

                case MemberKind.GetProperty:
                    blockSyntax = MemberBodySelector.GetPropertyAccessorBody((PropertyDeclarationSyntax)node.SyntaxNode, SyntaxKind.GetAccessorDeclaration);
                    break;
                case MemberKind.SetProperty:
                    blockSyntax = MemberBodySelector.GetPropertyAccessorBody((PropertyDeclarationSyntax)node.SyntaxNode, SyntaxKind.SetAccessorDeclaration);
                    break;

                case MemberKind.AddEventHandler:
                    blockSyntax = MemberBodySelector.GetEventAccessorBody((EventDeclarationSyntax)node.SyntaxNode, SyntaxKind.AddAccessorDeclaration);
                    break;
                case MemberKind.RemoveEventHandler:
                    blockSyntax = MemberBodySelector.GetEventAccessorBody((EventDeclarationSyntax)node.SyntaxNode, SyntaxKind.RemoveAccessorDeclaration);
                    break;
            }

            return blockSyntax;
        }

        private static BlockSyntax GetAccessorBody(AccessorListSyntax syntax, SyntaxKind kind)
        {
            AccessorDeclarationSyntax declarationSyntax = syntax.Accessors.SingleOrDefault(a => a.Kind() == kind);
            if (declarationSyntax != null)
                return declarationSyntax.Body;

            return null;
        }

        private static BlockSyntax GetPropertyAccessorBody(PropertyDeclarationSyntax syntax, SyntaxKind kind)
        {
            AccessorDeclarationSyntax declarationSyntax = syntax.AccessorList.Accessors.SingleOrDefault(a => a.Kind() == kind);
            if (declarationSyntax != null)
                return declarationSyntax.Body;

            return null;
        }

        private static BlockSyntax GetEventAccessorBody(EventDeclarationSyntax syntax, SyntaxKind kind)
        {
            AccessorDeclarationSyntax declarationSyntax = syntax.AccessorList.Accessors.SingleOrDefault(a => a.Kind() == kind);
            if (declarationSyntax != null)
                return declarationSyntax.Body;

            return null;
        }
    }
}
